package com.idanchuang.support.etcache.pubsub;

import com.idanchuang.support.etcache.exception.InvalidRemoteKeyException;
import com.idanchuang.support.etcache.remote.RemoteKey;
import com.idanchuang.support.etcache.remote.codec.RemoteKeyCodec;

/**
 * 缓存变更事件监听器的抽象实现
 * @author yjy
 * Created at 2021/12/23 7:49 下午
 */
public abstract class AbstractRemoteEventSubscriber implements RemoteEventSubscriber {

    /**
     * 事件队列
     */
    protected final SubEventQueue subEventQueue;

    protected final RemoteKeyCodec remoteKeyCodec;

    public AbstractRemoteEventSubscriber(RemoteKeyCodec remoteKeyCodec, SubEventQueue subEventQueue) {
        this.remoteKeyCodec = remoteKeyCodec;
        this.subEventQueue = subEventQueue;
    }

    @Override
    public void handle(byte[] eventBytes) {
        byte[] localInstanceBytes = AbstractRemoteEventPublisher.LOCAL_INSTANCE_BYTES;
        // 如果事件源是自身, 则忽略
        if (isFromSelf(eventBytes, localInstanceBytes)) {
            return;
        }
        // 将事件推入队列
        byte[] remoteKeyBytes = new byte[eventBytes.length - localInstanceBytes.length];
        System.arraycopy(eventBytes, localInstanceBytes.length, remoteKeyBytes, 0, remoteKeyBytes.length);

        try {
            RemoteKey remoteKey = remoteKeyCodec.decode(remoteKeyBytes);
            subEventQueue.push(new RemoteEvent(remoteKey.getCn(), remoteKey));
        } catch (InvalidRemoteKeyException ignored) {}
    }

    /**
     * 事件源是否是自身
     * @param eventBytes 事件消息
     * @param localInstanceBytes 自身标识
     * @return 是否?
     */
    private static boolean isFromSelf(byte[] eventBytes, byte[] localInstanceBytes) {
        for (int i = 0; i < localInstanceBytes.length; i++) {
            if (localInstanceBytes[i] != eventBytes[i]) {
                return false;
            }
        }
        return true;
    }

}
